/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package starter;

import chef.koordinator;
import chef.koordinatorHelper;
import java.io.File;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;

import java.io.IOException;
import java.util.Properties;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import org.omg.CORBA.IntHolder;

/**
 * 
 * @author baldow_m
 */
public class Starter extends javax.swing.JFrame {

//    private final String host = "lab21";
    private final String port = "10555";
    private final String prNr = "2";
    private final String grNr = "04";
    // public Starter starter;
    // Logger
    private Logger logger;
    private koordinator koordinator;
    private StarterGUI starterGUI;

    // Startarguments
    protected String[] startArguments;
    private String starterNr;
    private String ggtPath;

    public Starter() {
        logger = getLogger();
    }

    protected void initORB() {
        String[] args = new String[]{};
        Properties props = new Properties();
        props.put("org.omg.CORBA.ORBInitialHost", starterGUI.getNameserverOutput().getText());
        props.put("org.omg.CORBA.ORBInitialPort", port);
        ORB orb = ORB.init(args, props);

        NamingContext ctx;
        try {
            ctx = NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService"));

            NameComponent name[] = new NameComponent[]{new NameComponent(
                "chef", "")};

            koordinator = koordinatorHelper.narrow(ctx.resolve(name));
            logAndWrite(Level.INFO, "Connected to namingservice!");
        } catch (InvalidName e) {
            // e.printStackTrace();
            showMessageError("InvalidName", e.getMessage());
        } catch (NotFound e) {
            // e.printStackTrace();
            showMessageError("NotFound", e.getMessage());
        } catch (CannotProceed e) {
            // e.printStackTrace();
            showMessageError("CannotProceed", e.getMessage());
        } catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
            // e.printStackTrace();
            showMessageError("NamingContextPackage.InvalidName", e.getMessage());
        }

        // Getting values from koordinator
        steerSignal();
    }

    protected void steerSignal() {
        if (koordinator == null) {
            logAndWrite(Level.INFO, "No koordinator - stopping.");
            return;
        }

        // Corbaspecific
        IntHolder anzahl = new IntHolder();
        IntHolder verzoegerung = new IntHolder();
        IntHolder timeout = new IntHolder();
        boolean ok = false;
        for (int i = 0; i < 10; i++) {
            logAndWrite(Level.INFO, "Fetching values from Koordinator, #" + (i + 1));
            if (ok = (koordinator.getsteeringval(anzahl, verzoegerung, timeout) == 1)) {
                break;
            }
            try {
                // Try after 0.5sec again
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (!ok) {
            logAndWrite(Level.INFO, "Failed to fetch values - stopping.");
            return;
        } else {
            logAndWrite(Level.INFO, "Got values from Koordinator!");
            logAndWrite(Level.INFO, "Anzahl: " + anzahl.value);
            logAndWrite(Level.INFO, "Verzoegerung: " + verzoegerung.value);
            logAndWrite(Level.INFO, "Timeout: " + timeout.value);
        }

        // Starting ggts with given values
        startGGT(anzahl, verzoegerung, timeout);
    }

    private void startGGT(IntHolder anzahl, IntHolder verzoegerung,
            IntHolder timeout) {
        String[] arguments = new String[6];
        arguments[0] = ggtPath + "/unit";
        arguments[1] = startArguments[0];
        arguments[2] = startArguments[1] + starterGUI.getNameserverOutput().getText() + startArguments[2];
        arguments[3] = String.valueOf(timeout.value);
        arguments[4] = String.valueOf(verzoegerung.value);
//		arguments[6] = starterNr;
//        arguments[7] = "04";
        // arguments[6] = "";

        Runtime rt = Runtime.getRuntime();
        for (int i = 0; i < anzahl.value; i++) {
            arguments[5] = buildID(i);

            for (String s : arguments) {
                System.out.print(s + " ");
            }
            System.out.println("");
            try {
                rt.exec(arguments, new String[]{}, new File(ggtPath));
//				rt.exec("/home/pascal/vsp2/tunk/trunk/doc/cpp/abgabe/Slaves/unit `uname -n` -ORBInitRef NameService=corbaloc::localhost:10500/NameService 2 1 5 42");

                logAndWrite(Level.INFO, "Started ggt #" + (i + 1));
            } catch (IOException e) {
                e.printStackTrace();
                logAndWrite(Level.INFO, "Failed to start ggt #" + (i + 1) + "\nException: " + e.toString());
            }
        }
        logAndWrite(Level.INFO, "Shuting down starter...");
        System.exit(1);
    }

    private String buildID(int i) {
		String slaveNr = prNr + grNr + i + starterNr;
		return slaveNr;
	}

	protected void setValuesFromGui(JTextField starterNrTextField,
            JTextField ggtPathTextField) {
        starterNr = starterNrTextField.getText();
        ggtPath = ggtPathTextField.getText();
    }

    protected void setStarterGUI(StarterGUI starterGUI) {
        this.starterGUI = starterGUI;
    }

    protected void logAndWrite(Level level, String text) {
        logger.log(level, text);
        starterGUI.getStarterOutput().setText(
                starterGUI.getStarterOutput().getText() + text + "\n");
        starterGUI.getStarterOutput().setCaretPosition(
                starterGUI.getStarterOutput().getDocument().getLength());
    }

    /**
     * Creates a logger.
     *
     * @return
     */
    protected Logger getLogger() {
        FileHandler fhandler = null;
        if (logger == null) {
            try {
                fhandler = new FileHandler("Starter.log");
                fhandler.setFormatter(new SimpleFormatter());
                logger = Logger.getLogger("StarterLog");
                logger.addHandler(fhandler);
                logger.setLevel(Level.INFO);
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return logger;
    }

    /**
     * A simple dialog.
     *
     * @param titel
     * @param text
     */
    protected void showMessage(String titel, String text) {
        JOptionPane.showMessageDialog(null, text, titel,
                JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * A simple errordialog.
     *
     * @param titel
     * @param text
     */
    protected void showMessageError(String titel, String text) {
        JOptionPane.showMessageDialog(null, text, titel,
                JOptionPane.ERROR_MESSAGE);
    }
}
